import { z } from 'zod';
import { router, publicProcedure } from '../trpc';
import { protectedProcedure, adminProcedure } from '../middleware';
import { payoutService } from '../../services/payoutService';
import { createSuccessResponse, createErrorResponse } from '../../utils/response';
import { PayoutStatus, PaymentChannel } from '@prisma/client';
import { paymentService } from '../../services/paymentService';

// Input validation schemas
const createPayoutOrderSchema = z.object({
  uid: z.string().min(1, 'UID cannot be empty'),
  amount: z.number().positive('Payout amount must be greater than 0').max(500000, 'Payout amount cannot exceed 500000'),
  paymentChannel: z.nativeEnum(PaymentChannel, {
    errorMap: () => ({ message: 'Payment channel must be TOPPAY, PAY668, or LSPPAY' })
  }),
  paymentMethod: z.enum(['BankTransfer', 'qrPay'], {
    errorMap: () => ({ message: 'Payment method must be BankTransfer or qrPay' })
  }),
  receiverName: z.string().min(2, 'Receiver name must be at least 2 characters').max(50, 'Receiver name cannot exceed 50 characters'),
  receiverBankCard: z.string().min(1, 'Receiver bank card number cannot be empty').regex(/^\d{10,20}$/, 'Bank card number must be 10-20 digits'),
  bankCode: z.string().optional(),
  remark: z.string().max(200, 'Remark cannot exceed 200 characters').optional(),
  createdByName: z.string().min(2, 'Creator name must be at least 2 characters').max(50, 'Creator name cannot exceed 50 characters'),
});

const queryPayoutOrdersSchema = z.object({
  orderId: z.string().optional(),
  userId: z.number().int().positive().optional(),
  uid: z.string().optional(),
  status: z.nativeEnum(PayoutStatus).optional(),
  createdByUserId: z.number().int().positive().optional(),
  createdByName: z.string().optional(),
  confirmedByUserId: z.number().int().positive().optional(),
  page: z.number().int().positive().default(1),
  limit: z.number().int().positive().max(100).default(20),
});

const confirmPayoutOrderSchema = z.object({
  orderId: z.string().min(1, 'Order ID cannot be empty'),
  payoutPassword: z.string().min(6, 'Payout password must be at least 6 characters'),
});

const setPayoutPasswordSchema = z.object({
  newPassword: z.string().min(6, 'New password must be at least 6 characters').max(50, 'New password cannot exceed 50 characters'),
  currentPassword: z.string().optional(),
});

export const payoutRouter = router({
  /**
   * Create payment order
   */
  create: protectedProcedure
    .input(createPayoutOrderSchema)
    .mutation(async ({ input, ctx }) => {
      try {
        const result = await payoutService.createPayoutOrder({
          uid: input.uid,
          amount: input.amount,
          paymentChannel: input.paymentChannel,
          paymentMethod: input.paymentMethod,
          createdByUserId: ctx.user.userId,
          createdByName: input.createdByName,
          receiverName: input.receiverName,
          receiverBankCard: input.receiverBankCard,
          bankCode: input.bankCode,
          remark: input.remark,
        });

        return createSuccessResponse(result, 'Payment order created successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to create payment order',
          'PAYOUT_CREATE_ERROR'
        );
      }
    }),

  /**
   * Query payment orders
   */
  query: protectedProcedure
    .input(queryPayoutOrdersSchema)
    .query(async ({ input, ctx }) => {
      try {
        // Non-admin users can only view orders they created
        const queryInput = {
          ...input,
          createdByUserId: ctx.user.role === 'ADMIN' || ctx.user.role === 'SUB_ADMIN'
            ? input.createdByUserId
            : ctx.user.userId,
        };

        const result = await payoutService.queryPayoutOrders(queryInput);
        return createSuccessResponse(result, 'Payment order query successful');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to query payment orders',
          'PAYOUT_QUERY_ERROR'
        );
      }
    }),

  /**
   * Get payment record by order ID
   */
  getByOrderId: protectedProcedure
    .input(z.object({
      orderId: z.string().min(1, 'Order ID cannot be empty'),
    }))
    .query(async ({ input, ctx }) => {
      try {
        const record = await payoutService.getPayoutRecordByOrderId(input.orderId);

        if (!record) {
          return createErrorResponse('Order not found', 'ORDER_NOT_FOUND');
        }

        // Check permissions: only admin or order creator can view
        if (ctx.user.role !== 'ADMIN' && ctx.user.role !== 'SUB_ADMIN' &&
            record.createdByUserId !== ctx.user.userId) {
          return createErrorResponse('No permission to view this order', 'PERMISSION_DENIED');
        }

        return createSuccessResponse(record, 'Order details retrieved successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to get order details',
          'PAYOUT_GET_ERROR'
        );
      }
    }),

  /**
   * Admin confirm payment order (second confirmation)
   */
  confirm: adminProcedure
    .input(confirmPayoutOrderSchema)
    .mutation(async ({ input, ctx }) => {
      try {
        const result = await payoutService.confirmPayoutOrder({
          orderId: input.orderId,
          payoutPassword: input.payoutPassword,
          confirmedByUserId: ctx.user.userId,
        });

        return createSuccessResponse(result, 'Payment order confirmed successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to confirm payment order',
          'PAYOUT_CONFIRM_ERROR'
        );
      }
    }),

  /**
   * Execute payment (call payment interface)
   */
  execute: adminProcedure
    .input(z.object({
      orderId: z.string().min(1, 'Order ID cannot be empty'),
    }))
    .mutation(async ({ input }) => {
      try {
        const result = await payoutService.executePayment(input.orderId);

        return createSuccessResponse({
          success: result.success,
          platOrderNum: result.platOrderNum,
          errorMessage: result.errorMessage,
        }, result.success ? 'Payment executed successfully' : 'Payment execution failed');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to execute payment',
          'PAYOUT_EXECUTE_ERROR'
        );
      }
    }),

  /**
   * Cancel payment order
   */
  cancel: protectedProcedure
    .input(z.object({
      orderId: z.string().min(1, 'Order ID cannot be empty'),
    }))
    .mutation(async ({ input, ctx }) => {
      try {
        const record = await payoutService.getPayoutRecordByOrderId(input.orderId);

        if (!record) {
          return createErrorResponse('Order not found', 'ORDER_NOT_FOUND');
        }

        // Check permissions: admin or order creator can cancel
        if (ctx.user.role !== 'ADMIN' && ctx.user.role !== 'SUB_ADMIN' &&
            record.createdByUserId !== ctx.user.userId) {
          return createErrorResponse('No permission to cancel this order', 'PERMISSION_DENIED');
        }

        const result = await payoutService.cancelPayoutOrder(input.orderId, ctx.user.userId);
        return createSuccessResponse(result, 'Payment order cancelled successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to cancel payment order',
          'PAYOUT_CANCEL_ERROR'
        );
      }
    }),

  /**
   * Get user payment statistics
   */
  getUserStats: protectedProcedure
    .input(z.object({
      uid: z.string().min(1),
    }))
    .query(async ({ input, ctx }) => {
      try {
        // Check permissions: only admin can view user statistics
        if (ctx.user.role !== 'ADMIN' && ctx.user.role !== 'SUB_ADMIN') {
          return createErrorResponse('No permission to view user statistics', 'PERMISSION_DENIED');
        }

        const stats = await payoutService.getUserPayoutStats(input.uid);
        return createSuccessResponse(stats, 'User payment statistics retrieved successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to get user payment statistics',
          'PAYOUT_STATS_ERROR'
        );
      }
    }),

  /**
   * Admin query all orders
   */
  adminQuery: adminProcedure
    .input(queryPayoutOrdersSchema)
    .query(async ({ input }) => {
      try {
        const result = await payoutService.queryPayoutOrders(input);
        return createSuccessResponse(result, '管理员Payment order query successful');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Admin payment order query failed',
          'ADMIN_PAYOUT_QUERY_ERROR'
        );
      }
    }),

  /**
   * Set or update admin payment password
   */
  setPayoutPassword: adminProcedure
    .input(setPayoutPasswordSchema)
    .mutation(async ({ input, ctx }) => {
      try {
        await payoutService.setPayoutPassword(
          ctx.user.userId,
          input.newPassword,
          input.currentPassword
        );

        return createSuccessResponse(null, 'Payment password set successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to set payment password',
          'SET_PAYOUT_PASSWORD_ERROR'
        );
      }
    }),

  /**
   * Check if admin has set payment password
   */
  checkPayoutPassword: adminProcedure
    .query(async ({ ctx }) => {
      try {
        // 直接查询用户表检查是否设置了支付密码
        const { PrismaClient } = require('@prisma/client');
        const prisma = new PrismaClient();
        
        const user = await prisma.user.findUnique({
          where: { id: ctx.user.userId },
          select: { payoutPassword: true }
        });
        
        return createSuccessResponse({
          hasPayoutPassword: !!user?.payoutPassword
        }, 'Payment password status checked successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to check payment password status',
          'CHECK_PAYOUT_PASSWORD_ERROR'
        );
      }
    }),

  /**
   * Get available payment channels
   */
  getAvailableChannels: protectedProcedure
    .query(async () => {
      try {
        const channels = paymentService.getAvailableChannels();
        const channelInfo = channels.map(channel => ({
          value: channel,
          label: paymentService.getChannelDisplayName(channel),
          configured: paymentService.isChannelConfigured(channel)
        }));

        return createSuccessResponse({
          channels: channelInfo,
          count: channels.length
        }, 'Payment channels retrieved successfully');
      } catch (error) {
        return createErrorResponse(
          error instanceof Error ? error.message : 'Failed to get payment channels',
          'GET_CHANNELS_ERROR'
        );
      }
    }),

  /**
   * TopPay async notification processing (public interface)
   */
  topPayNotify: publicProcedure
    .input(z.object({
      code: z.string(),
      msg: z.string(),
      status: z.string(),
      method: z.string(),
      platOrderNum: z.string(),
      orderNum: z.string(),
      payMoney: z.string(),
      payFee: z.string(),
      transAccNo: z.string().optional(),
      platSign: z.string(),
    }))
    .mutation(async ({ input }) => {
      try {
        // TODO: Handle TopPay payment notification
        // Verify signature, update order status, etc.
        
        return 'SUCCESS';
      } catch (error) {
        console.error('TopPay payout notification processing failed:', error);
        throw new Error('FAILED');
      }
    }),

  /**
   * 668Pay async notification processing (public interface)
   */
  pay668Notify: publicProcedure
    .input(z.object({
      payOrderId: z.string(),
      mchOrderNo: z.string(),
      orderState: z.number(),
      amount: z.string(),
      customerName: z.string(),
      customerEmail: z.string(),
      customerPhone: z.string(),
      wayCode: z.string().optional(),
      extParam: z.string().optional(),
      sign: z.string(),
    }))
    .mutation(async ({ input }) => {
      try {
        // TODO: Handle 668Pay payment notification
        // Verify signature, update order status, etc.
        
        return 'SUCCESS';
      } catch (error) {
        console.error('668Pay payout notification processing failed:', error);
        throw new Error('FAILED');
      }
    }),
});